/*
 * Licensed to the Tai Ping Jin Ke
 *
 * Copyright (c) 2022 .
 * All rights reserved.
 * 项目名称：太平金科-基础组件封装层-SpringCloud组件封装-缺省实现
 * 版权说明：本软件属太平金融科技服务(上海)有限公司所有，在未获得太平金融科技服务(上海)有限公司正式授权情况下，任何企业和个人，不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。
 */
package com.taipingframework.cloud.web.openfeign;

import com.taipingframework.cloud.web.properties.FeignHeaderProperty;
import feign.Request;
import feign.RequestTemplate;
import feign.Response;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

/**
 * Reactive环境下
 * 默认实现FeignClient请求与响应两个阶段的回调
 */
@Slf4j
public final class ReactiveFeignClientAdvice implements FeignClientAdvice {
    private FeignHeaderProperty feignHeaderProperty;

    public ReactiveFeignClientAdvice(FeignHeaderProperty feignHeaderProperty) {
        this.feignHeaderProperty = feignHeaderProperty;
    }

    @Override
    public void beforeAdvice(RequestTemplate requestTemplate) {
        String url = requestTemplate.url();
        try {
            // 获取 在FeignClient调用过程中 需要被传递 的 HTTP请求头参数
            for (String name : feignHeaderProperty.getHeaders()) {
                log.info("【前置通知】feign远程调用接口 {} 时，忽略请求头参数 `{}` ，原因：WebFlux模式下未实现请求头重写功能", url, name);
            }

            /* 参数转发
            requestTemplate.query(paramName, paramValue);*/
        } catch (Exception e) {
            log.error("【前置通知】调用微服务({})时执行`自定义Feign请求拦截器`发生异常:{}", url, e.getMessage(), e);
        }
    }

    @Override
    public void returnAdvice(Response response, Request.Options options) {
        String url = response.request().url();
        try {
            // 获取 在FeignClient调用过程中 需要被传递 的 HTTP响应头参数
            for (String name : feignHeaderProperty.getHeaders()) {
                // 执行feign远程调用结束之后：
                // （1）获取到Feign回传响应头中的参数值必须有效
                // （2）当前HTTP请求对象的响应头中，该参数必须是无效的
                String value = FeignClientAdvice.readResponseHeader(response, name);
                String msg = StringUtils.isEmpty(value)
                        ? "【返回通知】feign远程调用接口 {} 结束，忽略值为空的响应头参数 `{}`"
                        : "【返回通知】feign远程调用接口 {} 结束，忽略响应头参数 `{}` ，原因：WebFlux模式下未实现响应头重写功能";
                log.info(msg, url, name);
            }
        } catch (Exception e) {
            log.error("【返回通知】调用微服务({})时执行`自定义Feign响应拦截器`发生异常:{}", url, e.getMessage(), e);
        }
    }
}
